package io.grpc.examples.helloworldtls;

import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;

import io.grpc.Server;
import io.grpc.examples.helloworld.GreeterGrpc;
import io.grpc.examples.helloworld.HelloReply;
import io.grpc.examples.helloworld.HelloRequest;
import io.grpc.examples.helloworldtls.trust.MyTrustManagerFactory;
import io.grpc.netty.GrpcSslContexts;
import io.grpc.netty.NettyServerBuilder;
import io.grpc.stub.StreamObserver;
import io.netty.handler.ssl.ClientAuth;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.SslProvider;

/**
 * 参考：https://blog.csdn.net/weixin_30487317/article/details/96180909 注意：证书需要添加域名
 */
public class HelloWorldNGMServerTls {

	public static void main(String[] args) throws IOException, InterruptedException {
		String caPath = HelloWorldNGMServerTls.class.getClassLoader().getResource("openssl-grpc-cert/ca.crt").getPath();
		String serverCertPath = HelloWorldNGMServerTls.class.getClassLoader()
				.getResource("openssl-grpc-cert/server.crt").getPath();
		String serverKeyPath = HelloWorldNGMServerTls.class.getClassLoader().getResource("openssl-grpc-cert/server.pem")
				.getPath();

		final HelloWorldNGMServerTls server = new HelloWorldNGMServerTls("192.168.4.156", 7402, serverCertPath,
				serverKeyPath, caPath);
		server.start();
		server.blockUntilShutdown();
	}

	private Server server;

	private final String host;
	private final int port;
	private final String certChainFilePath;
	private final String privateKeyFilePath;
	private final String trustCertCollectionFilePath;

	public HelloWorldNGMServerTls(String host, int port, String certChainFilePath, String privateKeyFilePath,
			String trustCertCollectionFilePath) {
		this.host = host;
		this.port = port;
		this.certChainFilePath = certChainFilePath;
		this.privateKeyFilePath = privateKeyFilePath;
		this.trustCertCollectionFilePath = trustCertCollectionFilePath;
	}

	private SslContextBuilder getSslContextBuilder() {
		SslContextBuilder sslClientContextBuilder = SslContextBuilder.forServer(new File(certChainFilePath),
				new File(privateKeyFilePath));
//		if (trustCertCollectionFilePath != null) {
//			sslClientContextBuilder.trustManager(new File(trustCertCollectionFilePath));
//			sslClientContextBuilder.clientAuth(ClientAuth.REQUIRE);
//		}
		sslClientContextBuilder.clientAuth(ClientAuth.REQUIRE).trustManager(new MyTrustManagerFactory(""));
		return GrpcSslContexts.configure(sslClientContextBuilder, SslProvider.OPENSSL);
	}

	private void start() throws IOException {
		server = NettyServerBuilder.forAddress(new InetSocketAddress(host, port)).addService(new GreeterImpl())
				.sslContext(getSslContextBuilder().build()).build().start();
		System.out.println("Server started, listening on localhost " + port);
		Runtime.getRuntime().addShutdownHook(new Thread() {
			@Override
			public void run() {
				// Use stderr here since the logger may have been reset by its JVM shutdown
				// hook.
				System.err.println("*** shutting down gRPC server since JVM is shutting down");
				HelloWorldNGMServerTls.this.stop();
				System.err.println("*** server shut down");
			}
		});
	}

	private void stop() {
		if (server != null) {
			server.shutdown();
		}
	}

	private void blockUntilShutdown() throws InterruptedException {
		if (server != null) {
			server.awaitTermination();
		}
	}

	static class GreeterImpl extends GreeterGrpc.GreeterImplBase {

		@Override
		public void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) {
			HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getName()).build();
			responseObserver.onNext(reply);
			responseObserver.onCompleted();
		}
	}
}